package net.pimpas.web.jsf.components.validators.operation;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import net.pimpas.logging.serviceprovider.LoggingServiceProvider;
import net.pimpas.logging.serviceprovider.LoggingServiceProviderFactoryImpl;
import net.pimpas.operation.exception.OperationException;
import net.pimpas.operation.serviceprovider.OperationServiceProvider;
import net.pimpas.operation.serviceprovider.OperationServiceProviderFactoryImpl;
import net.pimpas.resourcebundle.serviceprovider.ResourceBundleServiceProviderType;
import net.pimpas.util.reflection.ReflectionUtil;
import net.pimpas.web.jsf.components.validators.PimpasValidator;
import net.pimpas.web.jsf.util.ComponentInformation;

public class OperationValidator extends PimpasValidator {

	public static final String MESSAGE_KEY			= ComponentInformation.COMPONENT_VALIDATE_MESSAGE_KEY+".operation";
	public static final String VALIDATOR_ID			= ComponentInformation.COMPONENT_VALIDATE_ID+".operation";
	private String operation;
	private static final LoggingServiceProvider logger = 
		LoggingServiceProviderFactoryImpl.getLoggingServiceProvider(OperationValidator.class);
	
	public String getOperation() {
		return operation;
	}

	public void setOperation(String operation) {
		this.operation = operation;
	}
	
	protected OperationServiceProvider getOperationProvider( ) {
		return OperationServiceProviderFactoryImpl.getOperationServiceProvider();	
	}

	@Override
	protected void validateComponent(FacesContext context, UIComponent component, Object value) throws ValidatorException {
		OperationServiceProvider op = this.getOperationProvider(); 
		try {
			op.call(this.getOperation(), value);
		} catch (OperationException e) {
			// validator exception??
			if(ReflectionUtil.isSubclass(e.getCause().getClass(), ValidatorException.class)) {
				// throw
				throw new ValidatorException(((ValidatorException)e.getCause()).getFacesMessage());
			} else {
				// unknown error
				try {
					logger.debug(this.getBundle().getMessage(this.getClass(), "unknownOperationError", ResourceBundleServiceProviderType.LOG, e.getMessage()));
				} catch (Throwable e1) {
					
				}
				
				throw new RuntimeException(e);
			}
		}
	}
	
	@Override
	public Object saveState(FacesContext context) {
		Object[] ob = new Object[2];
		ob[0] = super.saveState(context);
		ob[1] = this.getOperation();
		
		return ob;
	}
	
	@Override
	public void restoreState(FacesContext context, Object state) {
		Object[] ob = (Object[]) state;
		super.restoreState(context, ob[0]);
		this.setOperation((String) ob[1]);
	}
}